home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 11587 / 11587.xpi / components / auth.js next >
Text File  |  2009-10-13  |  17KB  |  527 lines

  1. /* vim: set sw=2 sts=2 ts=8 et syntax=javascript: */
  2.  
  3. // Aviary authentication component.  Implements the aviaryIAuth interface.
  4. // This component also sets aviary-hide-tbitem="true" on windows in FF < 3.1.
  5.  
  6. var gAviaryAuth = {
  7.   kContractID: "@aviary.com/aviary-auth;1",
  8.   kServiceName: "Aviary Auth Service",
  9.   kClassID: Components.ID("{7AC8EEB4-8567-4675-B50F-441ED78DCD2A}"),
  10.  
  11.   kDefaultToolsList: "20,Falcon,3,Peacock,1,Phoenix,4,Raven,2,Toucan,6,Myna",
  12.   kLoginCookieName: "marketplaceauth",
  13.  
  14.   mIsLoggedIn: false, // cached value (last known state).
  15.   mToolsList: null,   // cached value (last known state).
  16.   mIsFirstWindow: true,
  17.   mCanCaptureFlash: false,
  18.   mAviaryServerHost: "aviary.com", // Reset from pref at domwindowopened.
  19.   mObsSvc: null,
  20.   mPearlUtilRequest: null,
  21.  
  22.   kLoginStatusTimerInterval: 350, // 0.35 seconds
  23.   mLoginStatusTimer: null,
  24.  
  25.   // nsISupports implementation.
  26.   QueryInterface: function (aIID)
  27.   {
  28.     if (!aIID.equals(Components.interfaces.nsISupports) &&
  29.         !aIID.equals(Components.interfaces.nsIClassInfo) &&
  30.         !aIID.equals(Components.interfaces.nsIFactory) &&
  31.         !aIID.equals(Components.interfaces.nsIObserver) &&
  32.         !aIID.equals(Components.interfaces.aviaryIAuth))
  33.     {
  34. dump("gAviaryAuth bad QI: " + aIID + "\n");
  35.       throw Components.results.NS_ERROR_NO_INTERFACE;
  36.     }
  37.  
  38.     return this;
  39.   },
  40.  
  41.   // nsIClassInfo implementation.
  42.   getInterfaces: function(aCount)
  43.   {
  44.     var iList = [ Components.interfaces.nsISupports,
  45.                   Components.interfaces.nsIClassInfo,
  46.                   Components.interfaces.nsIFactory,
  47.                   Components.interfaces.nsIObserver,
  48.                   Components.interfaces.aviaryIAuth ];
  49.     aCount.value = iList.length;
  50.     return iList;
  51.   },
  52.  
  53.   getHelperForLanguage: function (aLanguage)
  54.   {
  55.     return null;
  56.   },
  57.  
  58.   contractID: this.kContractID,
  59.   classDescription: this.kServiceName,
  60.   classID: this.kClassID,
  61.   implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
  62.   flags: Components.interfaces.nsIClassInfo.DOM_OBJECT,
  63.  
  64.   // nsIFactory implementation.
  65.   createInstance: function (aOuter, aIID)
  66.   {
  67.     if (null != aOuter)
  68.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  69.  
  70.     return this.QueryInterface(aIID);
  71.   },
  72.  
  73.   lockFactory: function (aDoLock) {},
  74.  
  75.   // nsIObserver implementation.
  76.   observe: function(aSubject, aTopic, aData)
  77.   {
  78.     if ("app-startup" == aTopic)
  79.     {
  80.       this.mToolsList = this.kDefaultToolsList;
  81.  
  82.       this.mObsSvc = Components.classes["@mozilla.org/observer-service;1"]
  83.                        .getService(Components.interfaces.nsIObserverService);
  84.       this.mObsSvc.addObserver(this, "domwindowopened", false);
  85.     }
  86.     else if ("domwindowopened" == aTopic)
  87.     {
  88.       if (this.mIsFirstWindow)
  89.       {
  90.         this.mIsFirstWindow = false;
  91.         this.mObsSvc.addObserver(this, "aviary:loginstatus", false);
  92.         this.mObsSvc.addObserver(this, "aviary:toolsavailable", false);
  93.         this.mObsSvc.addObserver(this, "cookie-changed", false);
  94.  
  95.         try
  96.         {
  97.           var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
  98.                               .getService(Components.interfaces.nsIPrefBranch);
  99.           var serverPrefix = prefSvc.getCharPref("aviary.serverPrefix");
  100.           var ioSvc = Components.classes["@mozilla.org/network/io-service;1"]
  101.                                 .getService(Components.interfaces.nsIIOService);
  102.           var serverURI = ioSvc.newURI(serverPrefix, null, null);
  103.           var host = this.getHostFromURI(serverURI);
  104.           if (host)
  105.             this.mAviaryServerHost = host;
  106.         } catch (e) {}
  107.  
  108.         // In Firefox 3.5, XMLHttpRequest fails if we use it right away.
  109.         //  Therefore, kick off our timer to do a "gettoollist" call.
  110.         this.startLoginStatusTimer();
  111.  
  112.         // Set mCanCaptureFlash based on Firefox version (>= 3.1).
  113.         var v =  Components.classes["@mozilla.org/xre/app-info;1"]
  114.                      .getService(Components.interfaces.nsIXULAppInfo).version;
  115.         var ffVersion = parseFloat(v);
  116.         this.mCanCaptureFlash = (ffVersion >= 3.1);
  117.       }
  118.  
  119.       // In Firefox versions prior to 3.1, we cannot capture Flash content in
  120.       // Aviary tool windows.  Arrange to be called after each XUL window loads
  121.       // so we can set aviary-hide-tbitem="true" to hide the capture toolbar
  122.       // item.
  123.       if (!this.mCanCaptureFlash && aSubject)
  124.       {
  125.         var _this = this;
  126.         aSubject.addEventListener("load",
  127.                        function(aEvent) {
  128.                           aEvent.currentTarget.removeEventListener("load",
  129.                                                     arguments.callee, false);
  130.                           _this.checkForToolsWindow(aEvent.currentTarget);
  131.                        }, false);
  132.       }
  133.     }
  134.     else if ("aviary:loginstatus" == aTopic)
  135.     {
  136.       this.mIsLoggedIn = ("true" == aData);
  137.       this.cancelLoginStatusTimer();
  138. //      dump("cached mIsLoggedIn is now: " + this.mIsLoggedIn + "\n");
  139.     }
  140.     else if ("aviary:toolsavailable" == aTopic)
  141.     {
  142.       this.mToolsList = aData;
  143. //      dump("cached tools is now: " + this.mToolsList + "\n");
  144.     }
  145.     else if ("cookie-changed" == aTopic)
  146.     {
  147.       if (aData == "cleared") // all cookies removed
  148.       {
  149. //        dump("all cookies cleared\n");
  150.         this.startLoginStatusTimer();
  151.       }
  152.       else if (aSubject instanceof Components.interfaces.nsICookie)
  153.       {
  154.         if (this.kLoginCookieName == aSubject.name)
  155.         {
  156.           // Check cookie host/domain against mAviaryServerHost (case
  157.           // insensitive match; remove leading and trailing '.' if present).
  158.           var host = aSubject.host.toLowerCase();
  159.           if ((host.length > 0) && ('.' == host.charAt(0)))
  160.             host = host.substr(1);
  161.           if ((host.length > 0) && ('.' == host.substr(-1)))
  162.             host = host.substr(0, host.length - 1);
  163.           if (this.mAviaryServerHost == host)
  164.           {
  165. // dump("cookie " + aData + " - " + aSubject.name + "=" + aSubject.value + "\n");
  166.             this.startLoginStatusTimer();
  167.           }
  168.         }
  169.       }
  170.     }
  171.     else if ("timer-callback" == aTopic)
  172.     {
  173.       this.mLoginStatusTimer = null;
  174.       var serverAuth = new AviaryServerAuth("gettoollist");
  175.     }
  176.   },
  177.  
  178.   // aviaryIAuth implementation.
  179.   get isLoggedIn()
  180.   {
  181.     return this.mIsLoggedIn;
  182.   },
  183.  
  184.   get toolsList()
  185.   {
  186.     return this.mToolsList;
  187.   },
  188.  
  189.   Logout: function()
  190.   {
  191.     var serverAuth = new AviaryServerAuth("logout");
  192.   },
  193.  
  194.   // internal functions.
  195.   startLoginStatusTimer: function()
  196.   {
  197.     if (this.mLoginStatusTimer)
  198.       this.mLoginStatusTimer.cancel();
  199.     else
  200.     {
  201.       this.mLoginStatusTimer = Components.classes["@mozilla.org/timer;1"]
  202.                                .createInstance(Components.interfaces.nsITimer);
  203.     }
  204.  
  205.     if (this.mLoginStatusTimer)
  206.     {
  207.       this.mLoginStatusTimer.init(this, this.kLoginStatusTimerInterval,
  208.                                   this.mLoginStatusTimer.TYPE_ONE_SHOT);
  209.     }
  210.   },
  211.  
  212.   cancelLoginStatusTimer: function()
  213.   {
  214.     if (this.mLoginStatusTimer)
  215.     {
  216.       this.mLoginStatusTimer.cancel();
  217.       this.mLoginStatusTimer = null;
  218.     }
  219.   },
  220.  
  221.   checkForToolsWindow: function(aWindow)
  222.   {
  223.     try
  224.     {
  225.       var win = aWindow.document.documentElement;
  226.       if ("navigator:browser" == win.getAttribute("windowtype"))
  227.         var tabListener = new AviaryTabListener(aWindow,
  228.                                                 this.mAviaryServerHost);
  229.     } catch (e) {}
  230.   },
  231.  
  232.   getHostFromURI: function(aURI)
  233.   {
  234.     try
  235.     {
  236.       return aURI.host; // This throws for URLs such as about:blank.
  237.     } catch (e) {}
  238.  
  239.     return null;
  240.   },
  241.  
  242.   endOfObject: true
  243. };
  244.  
  245.  
  246. // It would be better to nest this within gAviaryAuth.
  247. // aCommand can be one of:  "logout", "isloggedin", "gettoollist"
  248. function AviaryServerAuth(aCommand)
  249. {
  250.   this.init(aCommand)
  251. }
  252.  
  253. AviaryServerAuth.prototype =
  254. {
  255.   kServerURL: "",
  256.   kServerURLSuffix: "/apps/xmlapi/login.aspx",
  257.  
  258.   mCommand: null,
  259.   mRequest: null,
  260.  
  261.   init: function(aCommand)
  262.   {
  263.     if (!aCommand)
  264.     {
  265.       throw new Components.Exception("missing parameter",
  266.                                      Components.results.NS_ERROR_INVALID_ARG);
  267.     }
  268.  
  269.     try
  270.     {
  271.       var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
  272.                           .getService(Components.interfaces.nsIPrefBranch);
  273.       var serverPrefix = prefSvc.getCharPref("aviary.serverPrefix");
  274.       this.kServerURL = serverPrefix + this.kServerURLSuffix;
  275.     } catch (e) {}
  276.  
  277.     this.mCommand = aCommand;
  278.  
  279.     // Create and initialize request.
  280.     const kCI = Components.interfaces;
  281.     const kXMLHttpRequestCID = "@mozilla.org/xmlextras/xmlhttprequest;1";
  282.     this.mRequest = Components.classes[kXMLHttpRequestCID]
  283.                               .createInstance(kCI.nsIXMLHttpRequest);
  284.  
  285.     var self = this;
  286.     this.mRequest.onload = function() { self.onLoad(self); }
  287.     this.mRequest.onerror = function() { self.onError(self); }
  288.  
  289. //dump(aCommand + " - AviaryServerAuth init about to call .open()\n");
  290.     this.mRequest.open("POST", this.kServerURL, true);
  291.     if (!gAviaryAuth.mPearlUtilRequest) try
  292.     {
  293.       // Load Pearl Utility Request library.
  294.       var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
  295.                   .createInstance(Components.interfaces.mozIJSSubScriptLoader);
  296.       loader.loadSubScript("chrome://aviary/content/pearlutil-request.js");
  297.       gAviaryAuth.mPearlUtilRequest = com.aviary.talon.request;
  298.     } catch (e) {}
  299.  
  300.     if (gAviaryAuth.mPearlUtilRequest)
  301.     {
  302.       gAviaryAuth.mPearlUtilRequest.
  303.                           EnsureCookiesWillBeSent(this.mRequest.channel, null);
  304.     }
  305.  
  306.     this.mRequest.setRequestHeader("Content-type",
  307.                                    "application/x-www-form-urlencoded");
  308.     var formParams = "mode=" + encodeURIComponent(this.mCommand);
  309. // dump("auth request: " + formParams + "\n");
  310.  
  311.     this.mRequest.send(formParams);
  312.   },
  313.   
  314.   onLoad: function(aThisObj)
  315.   {
  316.     var succeeded = false;
  317.     try {
  318.       const kHttpChannelCID = Components.interfaces.nsIHttpChannel;
  319.       var channel = aThisObj.mRequest.channel.QueryInterface(kHttpChannelCID);
  320.       succeeded = channel.requestSucceeded;
  321.     } catch(e) { dump("onLoad: " + e + "\n"); }
  322.  
  323.     var responseText = aThisObj.mRequest.responseText;
  324. // dump(aThisObj.mCommand + " - auth response text:\n" + responseText + "\n\n\n");
  325.     var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
  326.                          .getService(Components.interfaces.nsIObserverService);
  327.     if (succeeded && obsSvc)
  328.     {
  329.       var toolsList = gAviaryAuth.kDefaultToolsList;
  330.  
  331.       if ("isloggedin" == aThisObj.mCommand)
  332.       {
  333.         var isLoggedIn = ("true" == responseText);
  334.         obsSvc.notifyObservers(null, "aviary:loginstatus", isLoggedIn);
  335.       }
  336.       else if ("gettoollist" == aThisObj.mCommand)
  337.       {
  338.         var isLoggedIn = (("failure" != responseText) &&
  339.                           (responseText.indexOf(',') > 0));
  340.         obsSvc.notifyObservers(null, "aviary:loginstatus", isLoggedIn);
  341.         if (isLoggedIn)
  342.           toolsList = responseText;
  343.         obsSvc.notifyObservers(null, "aviary:toolsavailable", toolsList);
  344.       }
  345.       else if ("logout" == aThisObj.mCommand)
  346.       {
  347.         obsSvc.notifyObservers(null, "aviary:loginstatus", false);
  348.         obsSvc.notifyObservers(null, "aviary:toolsavailable", toolsList);
  349.       }
  350.     }
  351.  
  352.     if (!succeeded)
  353.     {
  354.       aThisObj.onError(aThisObj);
  355.       return;
  356.     }
  357.   },
  358.  
  359.   onError: function(aThisObj)
  360.   {
  361.     var errMsg;
  362.     // TODO: fit this error message within a caller-provider message.
  363.     // TODO: report errors to user?
  364.     if (!errMsg)
  365.       errMsg = "Authentication failed."; // TODO: L10n
  366. //    dump(aThisObj.mCommand + " - auth error: " + errMsg + "\n");
  367.   },
  368.  
  369.   getBrowserWindow: function()
  370.   {
  371.     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  372.                        .getService(Components.interfaces.nsIWindowMediator);
  373.     return wm.getMostRecentWindow("navigator:browser");
  374.   },
  375.  
  376.   endOfObject: true
  377. }
  378.  
  379. function AviaryTabListener(aWindow, aServerHost)
  380. {
  381.   this.init(aWindow, aServerHost);
  382. }
  383.  
  384. AviaryTabListener.prototype =
  385. {
  386.   kAviaryToolsSuffix1: "/flash/",
  387.   kAviaryToolsSuffix2: "/apps/flash/",
  388.   kAviaryToolsSuffix3: "/launch/",
  389.   kCIWebProgress : Components.interfaces.nsIWebProgress,
  390.  
  391.   mWindow: null,
  392.   mServerHost: null,
  393.  
  394.   init: function(aWindow, aServerHost)
  395.   {
  396.     if (aServerHost)
  397.       this.mServerHost = aServerHost.toLowerCase();
  398.  
  399.     if (aWindow)
  400.     {
  401.       this.mWindow = aWindow.document.documentElement;
  402.       var tabBrowser = aWindow.document.getElementById("content");
  403.       tabBrowser.addProgressListener(this, this.kCIWebProgress.NOTIFY_LOCATION);
  404.     }
  405.   },
  406.  
  407.   // nsISupports:
  408.   QueryInterface: function(aIID)
  409.   {
  410.     if (aIID.equals(Components.interfaces.nsIWebProgressListener)
  411.         || aIID.equals(Components.interfaces.nsISupports)
  412.         || aIID.equals(Components.interfaces.nsISupportsWeakReference))
  413.     {
  414.       return this;
  415.     }
  416.  
  417.     throw Components.results.NS_NOINTERFACE;
  418.   },
  419.  
  420.   // nsIWebProgressListener:
  421.   onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {},
  422.  
  423.   onProgressChange: function(aWebProgress, aRequest,
  424.                               aCurrentSelfProgress, aMaxSelfProgress,
  425.                               aCurrentTotalProgress, aMaxTotalProgress) {},
  426.  
  427.   onLocationChange: function(aWebProgress, aRequest, aLocationURI)
  428.   {
  429.     if (aWebProgress && aLocationURI && this.mWindow)
  430.     {
  431.       var hideTBItem = false;
  432.       var host = gAviaryAuth.getHostFromURI(aLocationURI);
  433.       if (host && aLocationURI.path && (host.toLowerCase() == this.mServerHost))
  434.       {
  435.         var path = aLocationURI.path;
  436.         hideTBItem = this.startsWith(path, this.kAviaryToolsSuffix1)
  437.                      || this.startsWith(path, this.kAviaryToolsSuffix2)
  438.                      || this.startsWith(path, this.kAviaryToolsSuffix3);
  439.       }
  440.  
  441.       if (hideTBItem)
  442.         this.mWindow.setAttribute("aviary-hide-tbitem", "true");
  443.       else
  444.         this.mWindow.removeAttribute("aviary-hide-tbitem");
  445.     }
  446.   },
  447.  
  448.   onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {},
  449.   onSecurityChange: function(aWebProgress, aRequest, aState) {},
  450.  
  451.   // Private functions.
  452.   startsWith: function(aStr, aPrefix)
  453.   {
  454.     if (!aStr || !aPrefix)
  455.       return false;
  456.  
  457.  
  458.     var prefixLen = aPrefix.length;
  459.     return ((aStr.length >= prefixLen)
  460.             && (aPrefix == aStr.substr(0, prefixLen)));
  461.   },
  462.  
  463.   endOfObject: true
  464. }
  465.  
  466. var gAviaryAuthSvcModule =
  467. {
  468.   kICompReg: Components.interfaces.nsIComponentRegistrar,
  469.   kClassID: gAviaryAuth.kClassID,
  470.   kContractID: gAviaryAuth.kContractID,
  471.   kServiceName: gAviaryAuth.kServiceName,
  472.  
  473.   // nsISupports implementation.
  474.   QueryInterface: function (aIID)
  475.   {
  476.     if (aIID.equals(Components.interfaces.nsIModule) ||
  477.         aIID.equals(Components.interfaces.nsISupports))
  478.       return this;
  479.  
  480.     throw Components.results.NS_ERROR_NO_INTERFACE;
  481.   },
  482.  
  483.   // nsIModule implementation.
  484.   getClassObject: function (aCompMgr, aClassID, aIID)
  485.   {
  486.     if (!aClassID.equals(this.kClassID))
  487.       throw Components.results.NS_ERROR_NO_INTERFACE;
  488.     if (!aIID.equals(Components.interfaces.nsIFactory))
  489.       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  490.  
  491.     return gAviaryAuth.QueryInterface(aIID);
  492.   },
  493.  
  494.   registerSelf: function (aCompMgr, aFileSpec, aLocation, aType)
  495.   {
  496.     aCompMgr = aCompMgr.QueryInterface(this.kICompReg);
  497.     aCompMgr.registerFactoryLocation(this.kClassID, this.kServiceName,
  498.                                  this.kContractID, aFileSpec, aLocation, aType);
  499.  
  500.     var catMgr = Components.classes["@mozilla.org/categorymanager;1"]
  501.                          .getService(Components.interfaces.nsICategoryManager);
  502.     catMgr.addCategoryEntry("app-startup", this.kServiceName, this.kContractID,
  503.                             true, true);
  504.   },
  505.  
  506.   unregisterSelf: function (aCompMgr, aFileSpec, aLocation)
  507.   {
  508.     var catMgr = Components.classes["@mozilla.org/categorymanager;1"]
  509.                          .getService(Components.interfaces.nsICategoryManager);
  510.     catMgr.deleteCategoryEntry("app-startup", this.kServiceName, true);
  511.  
  512.     aCompMgr = aCompMgr.QueryInterface(this.kICompReg);
  513.     aCompMgr.unregisterFactoryLocation(this.kClassID, aFileSpec);
  514.   },
  515.  
  516.   canUnload: function (aCompMgr) { return true; },
  517.  
  518.   endOfObject: true
  519. };
  520.  
  521.  
  522. function NSGetModule(aCompMgr, aFileSpec)
  523. {
  524.   return gAviaryAuthSvcModule;
  525. }
  526.  
  527.